/*
 * LeafRegisterSerializer_test.cpp
 *
 *  Created on: Nov 4, 2012
 *      Author: m
 */

#include "LeafRegisterSerializer.h"
#include "BPlusTreeDefinitions.h"
#include "../../../physical_layer/physical_layer.h"

#include <memory>
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <sstream>

#define _SERIALIZE_MODE_ARG   "-s"
#define _DESERIALIZE_MODE_ARG "-d"
#define _BIN_BUFFER_SIZE 256

typedef enum
{
    serialize,
    deserialize,
    invalid
}
operation_mode_t;

std::string outfileName;
std::string infileName;
operation_mode_t mode;

void invalid_args()
{
    std::cerr << "Argumentos inválidos. "                                   << std::endl
            << "Uso: lrs_ts [-s|-d] infile outfile"                         << std::endl
            << "Descripción: Serializa/Deserializa registros de nodo hoja." << std::endl
            << "Modos:"                                                     << std::endl
            << "\t-s: serialize"                                            << std::endl
            << "\t-d: deserialize"                                          << std::endl;
    exit( 1 );
}

void parse_args( int argc, char* argv[] )
{
    if ( strcmp( argv[1], _SERIALIZE_MODE_ARG ) == 0 )
        mode = serialize;
    else
        if ( strcmp( argv[1], _DESERIALIZE_MODE_ARG ) == 0 )
            mode = deserialize;
        else
            mode = invalid;

    infileName = argv[2];
    outfileName = argv[3];
}

int main( int argc, char* argv[] )
{
    std::ifstream infile;
    std::ofstream outfile;
    std::string lineBuffer;
    std::stringstream ss;
    unsigned int relPos;
    unsigned int reserved;
    std::string  key;
    LeafRegisterSerializer serializer;
    physical::byte binaryBuffer[_BIN_BUFFER_SIZE];
    size_t serializedBytes;

    if ( argc < 4 )
        invalid_args();

    parse_args( argc, argv );

    switch ( mode )
    {
    case serialize:

        infile.open( infileName );
        outfile.open( outfileName, std::ios_base::binary | std::ios_base::trunc );

        // Lee registros de nodo hoja que contienen en cada línea:
        // key:  string
        // rpos: posición relativa
        // reserved: entero con signo reservado para uso posterior
        while( getline( infile , lineBuffer) )
        {
            ss.clear();
            ss.str( lineBuffer );
            ss >> key;
            ss >> relPos;
            ss >> reserved;

            LeafRegister_t leafRegister( key, { relPos, reserved } );

            serializedBytes = serializer.serialize( leafRegister, binaryBuffer );
            memset( binaryBuffer+serializedBytes, 0xFF, _BIN_BUFFER_SIZE-serializedBytes );

            outfile.write( binaryBuffer, _BIN_BUFFER_SIZE );
        }
        break;

    case deserialize:

        infile.open( infileName, std::ios_base::binary );
        outfile.open( outfileName, std::ios_base::trunc );

        while( infile.read( binaryBuffer, _BIN_BUFFER_SIZE ) )
        {
            std::shared_ptr< LeafRegister_t > leafRegisterPtr;

            serializer.deserialize( binaryBuffer, leafRegisterPtr );

            outfile << leafRegisterPtr->getKey() << " "
                    << leafRegisterPtr->getValue().relativePosition << " "
                    << leafRegisterPtr->getValue().reserved << std::endl;
        }
        break;

    case invalid:
        invalid_args();
        break;
    }

    infile.close();
    outfile.close();

    return 0;
}
